﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

namespace Azalea.ORMap
{
    public class CommandBuilder : ICommandBuilder
    {
        internal IDbContext _dbContext;
        private int _index;
        internal List<IDataParameter> _parameters = new List<IDataParameter>();
        internal StringBuilder _sqlBuilder = new StringBuilder();

        public CommandBuilder(IDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        #region internal members

        internal string AddParameter(string tableName, string field, object value, bool addSurfix)
        {
            DataColumn column = _dbContext.GetTableSchema(tableName).Columns[field];

            IDataParameter parameter = _dbContext.DbFactory.NewParameter();

            parameter.ParameterName = GetParameterName(field, addSurfix);
            parameter.DbType = _dbContext.DbFactory.GetDbTypeFromType(column.DataType);
            parameter.Direction = column.AutoIncrement ? ParameterDirection.Output : ParameterDirection.Input;
            parameter.Value = value ?? DBNull.Value;
            _parameters.Add(parameter);

            return parameter.ParameterName;
        }

        internal string QuotingKeyword(string keyword)
        {
            return _dbContext.DbFactory.Quoting(keyword);
        }

        internal string GetParameterName(string field, bool addSurfix)
        {
            string parameterName = _dbContext.DbFactory.GetParameterName(field);
            if (addSurfix)
            {
                parameterName += _index++;
            }
            return parameterName;
        }

        internal DataTable GetSchema(string tableName)
        {
            return _dbContext.GetTableSchema(tableName);
        }

        internal void HandleAutoIncrementColumn(string _tableName)
        {
            foreach (DataColumn column in GetSchema(_tableName).Columns)
            {
                if (column.AutoIncrement)
                {
                    string parameterName = AddParameter(_tableName, column.ColumnName, null, false);

                    _sqlBuilder.Append(";select ")
                        .Append(parameterName)
                        .Append("=")
                        .Append(_dbContext.DbFactory.GetFunctionNameToGetAutoIncrementValue());
                }
            }
        }

        #endregion

        #region ICommandBuilder Members

        public IDbCommand Done(bool clearBuilder)
        {
            IDbCommand cmd = _dbContext.DbFactory.NewCommand();
            cmd.CommandText = _sqlBuilder.ToString();
            _parameters.ForEach();

            if (clearBuilder)
            {
                _sqlBuilder.Length = 0;
                _parameters.Clear();
            }

            return cmd;
        }

        public ISqlInsert Insert()
        {
            return new SqlInsert(this);
        }

        public ISqlDelete Delete()
        {
            return new SqlDelete(this);
        }

        public ISqlUpdate Update()
        {
            return new SqlUpdate(this);
        }

        public ISqlSelect Select()
        {
            return new SqlSelect(this);
        }

        #endregion

        public override string ToString()
        {
            var sb = new StringBuilder();
            foreach (IDataParameter param in _parameters)
            {
                sb.AppendLine(param.ParameterName + ": " + param.Value);
            }

            return _sqlBuilder + Environment.NewLine + sb;
        }
    }
}